/*
 * $Id: SubmittedChangelistView.java 23 2002-09-29 13:59:30Z bpruessmann $
 *
 * Copyright (c) 2001 Boris Pruessmann and others.
 * All rights reserved.   This program and the accompanying materials
 * are made available under the terms of the Common Public License v0.5
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v05.html
 * 
 * Contributors:
 *    Boris Pruessmann - Initial implementation.
 */
package net.sourceforge.p4eclipse.ui.views;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;

import net.sourceforge.p4eclipse.core.PerforceException;
import net.sourceforge.p4eclipse.core.Policy;
import net.sourceforge.p4eclipse.core.api.IChangesResult;
import net.sourceforge.p4eclipse.core.api.IInfoResult;
import net.sourceforge.p4eclipse.internal.ui.views.submitted.FilterCurrentClientAction;
import net.sourceforge.p4eclipse.internal.ui.views.submitted.FilterCurrentUserAction;
import net.sourceforge.p4eclipse.internal.ui.views.submitted.UserFilter;
import net.sourceforge.p4eclipse.ui.PerforceUIPlugin;
import net.sourceforge.p4eclipse.ui.dialogs.ChangeSpecDialog;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.ActionContributionItem;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.viewers.ColumnLayoutData;
import org.eclipse.jface.viewers.ColumnPixelData;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.TableLayout;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.IViewSite;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.part.ViewPart;

/**
  * @version 	$Revision: 23 $
  * @author		<a href="mailto:bpruessmann@users.sourceforge.net">Boris Pruessmann</a>
  */
public class SubmittedChangelistView extends ViewPart
{
	public static final String ID = PerforceUIPlugin.ID + ".ui.views.SubmittedChangelistView"; //$NON-NLS-1$		
	
	private static final String TAG_COLUMN = "column"; //$NON-NLS-1$
	private static final String TAG_NUMBER = "number"; //$NON-NLS-1$
	private static final String TAG_WIDTH = "width"; //$NON-NLS-1$

	private Object root;
	private Table table;
	private TableViewer viewer;
	
	private IMemento memento;

	private Action refreshAction;
	private FilterCurrentClientAction filterClientAction;
	private FilterCurrentUserAction filterUserAction;
	
	private InternalContentProvider contentProvider = new InternalContentProvider();
		
	private String columnHeaders[] = { "Changelist",
		                               "Date",
		                               "User",
		                               "Description" };

	private ColumnLayoutData columnLayouts[] = { new ColumnPixelData(70, true),
	                                             new ColumnPixelData(70, true),
	                                             new ColumnPixelData(110, true),
	                                             new ColumnPixelData(200, true) };	

	/** @see IViewPart#init(IViewSite, IMemento) */
	public void init(IViewSite site, IMemento memento)
		throws PartInitException
	{
		super.init(site, memento);
		this.memento = memento;
	}
	
	/** @see IWorkbenchPart#createPartControl(Composite) */
	public void createPartControl(Composite parent)
	{
		root = new Object();
		 
		createTable(parent);
		viewer = new TableViewer(table);
		viewer.setUseHashlookup(true);	
		viewer.setContentProvider(contentProvider);
		viewer.setLabelProvider(new InternalLabelProvider());			
		viewer.getControl().addKeyListener(new KeyAdapter() 
			{
				public void keyPressed(KeyEvent event) 
				{
					if (event.keyCode == SWT.F5) 
						refreshAction.run();
				}
			});
		createTableColumns();
				
		getSite().setSelectionProvider(viewer);
		contributeActions();

		viewer.setInput(root);
		memento = null;
	}
	
	private void createTable(Composite parent)
	{
		table = new Table(parent, SWT.H_SCROLL | SWT.V_SCROLL | SWT.FULL_SELECTION);
		table.setLinesVisible(true);
	}
	
	private void createTableColumns()
	{
		if(memento != null) 
		{
			//restore columns width
			IMemento children[] = memento.getChildren(TAG_COLUMN);
			if (children != null) 
			{
				for (int i = 0; i < children.length; i++) 
				{
					Integer val = children[i].getInteger(TAG_NUMBER);
					if (val != null) 
					{
						int index = val.intValue();
						val = children[i].getInteger(TAG_WIDTH);
						if (val != null) 
							columnLayouts[index] = new ColumnPixelData(val.intValue(), true);
					}
				}
			}
		}
		
		
		TableLayout layout = new TableLayout();
		table.setLayout(layout);
		table.setHeaderVisible(true);		
		
		for (int i = 0; i < columnHeaders.length; i++) 
		{
			layout.addColumnData(columnLayouts[i]);

			TableColumn tc = new TableColumn(table, SWT.NONE, i);
			tc.setResizable(columnLayouts[i].resizable);
			tc.setText(columnHeaders[i]);
		}		
	}

	/** 
	  * Contribute actions to the view. 
	  */
	private void contributeActions() 
	{
		viewer.addDoubleClickListener(
			new IDoubleClickListener() 
			{
				public void doubleClick(DoubleClickEvent e) 
				{
					IStructuredSelection sel = (IStructuredSelection)viewer.getSelection();
					IAdaptable element = (IAdaptable)sel.getFirstElement();
					if (element instanceof IChangesResult)
					{
						try
						{
							ChangeSpecDialog dialog = ChangeSpecDialog.newChangeSpecDialog(null, ((IChangesResult)element).getChangelist());
							dialog.setReadOnly(true);
							dialog.open();
						}
						catch (PerforceException ex)
						{
							ErrorDialog.openError(null, "Perforce Error", "Failure.", ex.getStatus());
						}
					}
				}
			});
		
		// Refresh (toolbar)
		refreshAction = new Action("Refresh View", PerforceUIPlugin.getPlugin().getImageDescriptor(PerforceUIPlugin.IMG_REFRESH)) 
			{
				public void run() 
				{
					contentProvider.reset();
					viewer.refresh();
				}
			};

		filterUserAction = FilterCurrentUserAction.newInstance(viewer, "Current User");
		filterClientAction = FilterCurrentClientAction.newInstance(viewer, "Current Client");		
			
			
		// Create the popup menu
		MenuManager menuMgr = new MenuManager();
		Table table = viewer.getTable();
		Menu menu = menuMgr.createContextMenu(table);
		menuMgr.addMenuListener(new IMenuListener() 
			{
				public void menuAboutToShow(IMenuManager manager) 
				{
					// Misc additions go last
					manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));				
				}
			});
		menuMgr.setRemoveAllWhenShown(true);
		table.setMenu(menu);
		getSite().registerContextMenu(menuMgr, viewer);
	
		// Create the local tool bar
		IActionBars bars = getViewSite().getActionBars();
		IToolBarManager tbm = bars.getToolBarManager();
		tbm.add(refreshAction);
		tbm.update(false);	
		
		MenuManager filtersMenuManager = new MenuManager("Filters");
		filtersMenuManager.add(filterUserAction);
		filtersMenuManager.add(filterClientAction);		
		bars.getMenuManager().add(filtersMenuManager);
	}

	/** @see IWorkbenchPart#setFocus() */
	public void setFocus()
	{
		Policy.assertNotNull(viewer);
		viewer.getControl().setFocus();
	}
			
	/** @see IViewPart#saveState(IMemento) */
	public void saveState(IMemento memento)
	{
		//save columns width
		Table table = viewer.getTable();
		TableColumn columns[] = table.getColumns();
		
		//check whether it has ever been layed out		
		boolean shouldSave = false;
		for (int i = 0; i < columns.length; i++)
		 {
			if (columnLayouts[i].resizable && columns[i].getWidth() != 0)
			 {
				shouldSave = true;
				break;
			}
		}
		
		if (shouldSave) 
		{
			for (int i = 0; i < columns.length; i++) 
			{
				if (columnLayouts[i].resizable) 
				{
					IMemento child = memento.createChild(TAG_COLUMN);
					child.putInteger(TAG_NUMBER,i);
					child.putInteger(TAG_WIDTH,columns[i].getWidth());
				}
			}
		}
	}		
		
	private class InternalContentProvider implements IStructuredContentProvider
	{
		private IChangesResult[] changesResult;
		
		/** @see IStructuredContentProvider#getElements(Object) */
		public Object[] getElements(Object parent)
		{
			if (changesResult == null)
			{
				changesResult = new IChangesResult[0];			
				if (parent == root)
				{
					try
					{
						changesResult = PerforceUIPlugin.getClient().changes("submitted", 100);
					}
					catch (PerforceException e)
					{
						PerforceUIPlugin.getPlugin().log(e.getStatus());
					}
				}
			}
	
			return changesResult;
		}

		/** resets the IChangesResult "cache". */
		public void reset()
		{
			changesResult = null;
		}

		/** @see IContentProvider#dispose() */
		public void dispose()
		{
			changesResult = null;
		}

		/** @see IContentProvider#inputChanged(Viewer, Object, Object) */
		public void inputChanged(Viewer viewer, Object oldInput, Object newInput)
		{
		}
	}
	
	private static class InternalLabelProvider extends LabelProvider implements ITableLabelProvider
	{
		/** @see ITableLabelProvider#getColumnImage(Object, int) */
		public Image getColumnImage(Object element, int columnIndex)
		{
			if (!(element instanceof IChangesResult))
				return null;
			
			if (columnIndex == 0)			
				return PerforceUIPlugin.getPlugin().getImageDescriptor(PerforceUIPlugin.IMG_SUBMITTED_CHANGELIST).createImage();
			else
				return null;
		}

		/** @see ITableLabelProvider#getColumnText(Object, int) */
		public String getColumnText(Object element, int columnIndex)
		{
			if (!(element instanceof IChangesResult))
				return null;
			
			IChangesResult changesResult = (IChangesResult)element;	
			switch (columnIndex)
			{
				case 0:
					return MessageFormat.format("{0,number,00000}", new Object[] {changesResult.getChangelist()});
					
				case 1:
					return SimpleDateFormat.getDateInstance(SimpleDateFormat.MEDIUM).format(changesResult.getDate());
					
				case 2:
					return changesResult.getUserName() + "@" + changesResult.getClientName();
					
				case 3:
					return cleanup(changesResult.getDescription());
					
				default:
					Policy.assertTrue(false);
			}
			
			return ""; //$NON-NLS-1$
		}
		
		/** Returns a version of text with CR/LF converted to spaces. */
		private String cleanup(String text)
		{
			StringBuffer result = new StringBuffer();
			BufferedReader reader = new BufferedReader(new StringReader(text));

			try
			{
				String line = null;
				while ((line = reader.readLine()) != null)
				{
					result.append(line).append(" "); //$NON-NLS-1$
				}
				
				return result.toString();
			}
			catch (IOException e)
			{
				PerforceUIPlugin.getPlugin().logError("InternalLabelProvider.cleanup failed.", e);
			}
			
			return text;					
		}

	}
	
	}
